namespace Inplay
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Globalization;
    using System.Windows;
    using System.Windows.Browser;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Shapes;
    using System.Windows.Threading;

    public partial class Page : Canvas
    {
        private IDictionary<string, string> startupArguments;
        private string source = "Test.wmv";
        private string background = "40FFFFFF";
        private double volume = 0.5f;
        private bool play = true;
        private int downloadAnimation = 1;
        private DispatcherTimer timer;

        public Page(IDictionary<string, string> startupArguments)
        {
            this.startupArguments = startupArguments;
            this.Loaded += this.Page_Loaded;
            this.InitializeComponent();
        }

        private void Page_Loaded(object sender, EventArgs args)
        {
            this.Height = Application.Current.Host.Content.ActualHeight;
            this.Width = Application.Current.Host.Content.ActualWidth;

            this.ParseArguments();

            this.PositionSlider.PropertyChanged += new PropertyChangedEventHandler(this.PositionSlider_PropertyChanged);

            this.VolumeSlider.Total = 100;
            this.VolumeSlider.PropertyChanged += new PropertyChangedEventHandler(this.VolumeSlider_PropertyChanged);

            this.PlayButton.CheckedChanged += new EventHandler(this.PlayButton_CheckedChanged);

            this.Player.MediaOpened += new RoutedEventHandler(this.Player_MediaOpened);
            this.Player.MediaEnded += new RoutedEventHandler(this.Player_MediaEnded);
            this.Player.MouseLeftButtonDown += new MouseButtonEventHandler(this.Player_MouseLeftButtonDown);
            this.Player.DownloadProgressChanged += new RoutedEventHandler(this.Player_DownloadProgressChanged);

            this.Player.AutoPlay = false;
            this.Player.Source = new Uri(this.source, UriKind.RelativeOrAbsolute);
            this.Player.Volume = this.volume;

            uint color = uint.Parse(this.background, NumberStyles.HexNumber);
            this.Background = new SolidColorBrush(Color.FromArgb((byte)(color >> 24), (byte)((color >> 16) & 0xff), (byte)((color >> 8) & 0xff), (byte)(color & 0xff)));

            Application.Current.Host.Content.Resized += new EventHandler(this.BrowserHost_Resize);

            this.PlayState = this.play;

            this.Timer_Tick(this, EventArgs.Empty);

            this.timer = new DispatcherTimer();
            this.timer.Interval = new TimeSpan(0, 0, 0, 0, 100);
            this.timer.Tick += new EventHandler(this.Timer_Tick);
            this.timer.Start();
        }

        void Player_DownloadProgressChanged(object sender, RoutedEventArgs e)
        {
            if (this.Player.DownloadProgress == 1)
                downloadTextbox.Text = "";
        }

        private void Player_MediaOpened(object sender, EventArgs e)
        {
            this.PlayState = this.play;
            this.Resize();
        }

        private void Player_MediaEnded(object sender, EventArgs e)
        {
            this.Player.Position = new TimeSpan(0, 0, 0);
        }

        private void Player_MouseLeftButtonDown(object sender, MouseEventArgs e)
        {
            Application.Current.Host.Content.IsFullScreen = !Application.Current.Host.Content.IsFullScreen;
            this.Resize();
        }

        private void BrowserHost_Resize(object sender, EventArgs e)
        {
            this.Resize();
        }

        private void Resize()
        {
            double width = Application.Current.Host.Content.ActualWidth;
            double height = Application.Current.Host.Content.ActualHeight;

            if ((width != 0) && (height != 0))
            {
                Canvas.SetTop(this.ControlPanel, height - this.ControlPanel.Height);

                this.SetClip(this, 0, 0, width, height, 4);

                height = height - ControlPanel.Height - 1;

                if (Application.Current.Host.Content.IsFullScreen)
                {
                    this.SetClip(this.Player, 0, 0, width, height, 0);
                }
                else if (height > 0)
                {
                    int left = 4;
                    int top = 4;
                    width = width - 4 - 4;
                    height = height - 4;

                    if (this.Player.NaturalVideoHeight != 0)
                    {
                        double naturalRatio = (double)this.Player.NaturalVideoWidth / (double)this.Player.NaturalVideoHeight;
                        double playerRatio = width / height;

                        if (naturalRatio > playerRatio)
                        {
                            height = width / naturalRatio;
                        }
                        else
                        {
                            width = height * naturalRatio;
                        }
                    }

                    this.SetClip(this.Player, left, top, width, height, 4);
                }

                this.ControlPanel.Visibility = Visibility.Visible;
            }
        }

        private void SetClip(FrameworkElement element, double left, double top, double width, double height, double radius)
        {
            RectangleGeometry clip = new RectangleGeometry()
            {
                Rect = new Rect(0, 0, width, height),
                RadiusX = radius,
                RadiusY = radius,
            };

            element.Width = width;
            element.Height = height;
            element.Clip = clip;
            Canvas.SetLeft(element, left);
            Canvas.SetTop(element, top);
        }

        private void PlayButton_CheckedChanged(object sender, EventArgs e)
        {
            if (this.PlayButton.Checked)
            {
                this.play = true;
                this.Player.Play();
            }
            else
            {
                this.play = false;
                this.Player.Pause();
            }
        }

        private void PositionSlider_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            this.Player.Position = new TimeSpan(0, 0, (int)this.PositionSlider.Value);

            if (this.PlayButton.Checked)
            {
                this.Player.Play();
            }
        }

        private void VolumeSlider_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            this.Player.Volume = this.VolumeSlider.Value / 100f;
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            if (this.Player.NaturalDuration.HasTimeSpan)
            {
                this.PositionSlider.Total = this.Player.NaturalDuration.TimeSpan.TotalSeconds;
                this.PositionSlider.Value = this.Player.Position.TotalSeconds;
            }

            this.VolumeSlider.Value = this.Player.Volume * 100f;
            if (this.Player.DownloadProgress < 1)
                switch (downloadAnimation)
                {
                    case 1:
                        downloadTextbox.Text = "downloading .";
                        downloadAnimation = 2;
                        break;
                    case 2:
                        downloadTextbox.Text = "downloading . .";
                        downloadAnimation = 3;
                        break;
                    case 3:
                        downloadTextbox.Text = "downloading . . .";
                        downloadAnimation = 1;
                        break;
                }
        }

        private bool PlayState
        {
            get { return this.PlayButton.Checked; }
            set { this.PlayButton.Checked = value; }
        }

        private void ParseArguments()
        {
            if (this.startupArguments.ContainsKey("source"))
            {
                this.source = this.startupArguments["source"];
            }

            if (this.startupArguments.ContainsKey("volume"))
            {
                this.volume = double.Parse(this.startupArguments["volume"]);
            }

            if (this.startupArguments.ContainsKey("background"))
            {
                this.background = this.startupArguments["background"];
            }

            if (this.startupArguments.ContainsKey("play"))
            {
                this.play = bool.Parse(this.startupArguments["play"]);
            }

            if (this.startupArguments.ContainsKey("id"))
            {
                string name = this.startupArguments["id"];

                if (HtmlPage.Document.QueryString.ContainsKey(name))
                {
                    string queryString = HtmlPage.Document.QueryString[name];

                    string[] parameters = queryString.Split(new char[] { ',' });
                    foreach (string parameter in parameters)
                    {
                        int index = parameter.IndexOf(':');
                        if (index != -1)
                        {
                            string parameterName = parameter.Substring(0, index);
                            string parameterValue = parameter.Substring(index + 1);

                            switch (parameterName)
                            {
                                case "source":
                                    this.source = parameterValue;
                                    break;

                                case "volume":
                                    this.volume = double.Parse(parameterValue);
                                    break;

                                case "background":
                                    this.background = parameterValue;
                                    break;

                                case "play":
                                    this.play = bool.Parse(parameterValue);
                                    break;
                            }
                        }
                    }
                }
            }
        }
    }

    public class CheckBox : Canvas
    {
        public event EventHandler CheckedChanged;

        private bool pressed = false;
        private bool isChecked = true;

        public CheckBox()
        {
            this.MouseEnter += new MouseEventHandler(this.Button_MouseEnter);
            this.MouseLeave += new MouseEventHandler(this.Button_MouseLeave);
            this.MouseLeftButtonDown += new MouseButtonEventHandler(this.Button_MouseLeftButtonDown);
            this.MouseLeftButtonUp += new MouseButtonEventHandler(this.Button_MouseLeftButtonUp);
        }

        public bool Checked
        {
            get
            {
                return this.isChecked;
            }

            set
            {
                if (value != this.isChecked)
                {
                    Canvas canvas1 = (Canvas)this.Children[1];
                    Canvas canvas2 = (Canvas)this.Children[2];

                    this.Children.RemoveAt(1);
                    this.Children.Add(canvas1);

                    canvas1.Opacity = 0;
                    canvas2.Opacity = 1;

                    this.isChecked = value;

                    this.OnCheckedChanged(EventArgs.Empty);
                }
            }
        }

        protected virtual void OnCheckedChanged(EventArgs e)
        {
            if (this.CheckedChanged != null)
            {
                this.CheckedChanged(this, e);
            }
        }

        private void Button_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e)
        {
            Rectangle border = (Rectangle)this.Children[0];
            border.StrokeThickness = 2;
        }

        private void Button_MouseLeave(object sender, EventArgs e)
        {
            Rectangle border = (Rectangle)this.Children[0];
            border.StrokeThickness = 1;
            this.SetPressed(false);
        }

        private void Button_MouseLeftButtonDown(object sender, MouseEventArgs e)
        {
            this.SetPressed(true);
        }

        private void Button_MouseLeftButtonUp(object sender, MouseEventArgs e)
        {
            this.SetPressed(false);

            this.Checked = !this.Checked;
        }

        private void SetPressed(bool value)
        {
            Rectangle border = (Rectangle)this.Children[0];
            Canvas canvas = (Canvas)this.Children[1];

            if (value)
            {
                border.Fill = new SolidColorBrush(Colors.White);

                for (int i = 0; i < canvas.Children.Count; i++)
                {
                    Shape shape = (Shape)canvas.Children[i];
                    shape.Stroke = new SolidColorBrush(Colors.Black);
                    shape.Fill = new SolidColorBrush(Colors.Black);
                }
            }
            else
            {
                border.Fill = new SolidColorBrush(Colors.Transparent);

                for (int i = 0; i < canvas.Children.Count; i++)
                {
                    Shape shape = (Shape)canvas.Children[i];
                    shape.Stroke = new SolidColorBrush(Colors.White);
                    shape.Fill = new SolidColorBrush(Colors.White);
                }
            }

            this.pressed = value;
        }
    }

    public class Slider : Canvas, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private double total;
        private double value;
        private bool mouseDown;

        public Slider()
        {
            this.MouseLeftButtonDown += new MouseButtonEventHandler(this.Slider_MouseLeftButtonDown);
            this.MouseLeftButtonUp += new MouseButtonEventHandler(this.Slider_MouseLeftButtonUp);
            this.MouseMove += new MouseEventHandler(this.Slider_MouseMove);
            this.MouseLeave += new MouseEventHandler(this.Slider_MouseLeave);
        }

        private void Slider_MouseLeftButtonDown(object sender, MouseEventArgs e)
        {
            this.mouseDown = true;
            this.Update(e.GetPosition(this).X);
        }

        private void Slider_MouseLeftButtonUp(object sender, MouseEventArgs e)
        {
            this.mouseDown = false;
        }

        private void Slider_MouseMove(object sender, MouseEventArgs e)
        {
            if (this.mouseDown)
            {
                this.Update(e.GetPosition(this).X);
            }
        }

        private void Slider_MouseLeave(object sender, EventArgs e)
        {
            this.mouseDown = false;
        }

        public double Total
        {
            set
            {
                this.total = value;
                this.Update();
            }

            get
            {
                return this.total;
            }
        }

        public double Value
        {
            set
            {
                if (this.value != value)
                {
                    this.value = value;
                    this.Update();
                }
            }

            get
            {
                return this.value;
            }
        }

        private void Update()
        {
            Rectangle border = (Rectangle)this.Children[0];
            Rectangle content = (Rectangle)this.Children[1];

            if (this.total == 0)
            {
                content.Width = 0;
            }
            else
            {
                double width = (this.value * border.Width) / this.total;
                if (width < 1)
                {
                    width = 0;
                }

                content.Width = width;
            }
        }

        private void Update(double position)
        {
            Rectangle border = (Rectangle)this.Children[0];

            if (position < 0)
            {
                position = 0;
            }

            if (position > border.Width)
            {
                position = border.Width;
            }

            this.value = position * this.total / border.Width;
            this.Update();
            this.OnPropertyChanged(new PropertyChangedEventArgs("Value"));
        }

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, e);
            }
        }
    }
}